package com.gosling.cloudspace.job;

import com.gosling.cloudspace.config.ThreadPool;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;

import java.util.*;
import java.util.concurrent.CountDownLatch;

/**
 * 定时任务
 *
 * @email 1793327033@qq.com
 * @classname Jobs
 * @author: osc_lihonglin
 * @date: 2021/10/9 14:10
 */
//@Component
public class XmlAndEleCronJobs {
    protected final Logger logger = LoggerFactory.getLogger(XmlAndEleCronJobs.class);
    //每批次处理数据量
    private final int processSize = 200;
    @Autowired
    private ThreadPool taskExecutor;
    //电子文件定时任务启用开关 open/close
    @Value("${schedule.electronic.status}")
    private String cronStatus;

    //eep定时任务开关 open/close
    @Value("${schedule.eep.status}")
    private String eepCronStatus;

    /**
     * 定时创建或者更新xml
     * 如果只有创建时间的，说明是原始型没有被修改
     * 有修改时间的说明是修改型或者生成多次
     * TODO 会有表不存在的情况！
     *
     * @author: osc_lihonglin
     * @date: 2021/11/24 16:09
     */
    @Scheduled(cron = "${schedule.eep.cron}")
    public void createAndUpdateXmlCronJob() {
        if (eepCronStatus.equals("open")) {
            logger.info("执行开始！" + System.currentTimeMillis());
            Map<String, Object> condition = new HashMap<>();
            condition.put("notTemplate", "fonds_common_temp");
            condition.put("archivee_status", "01");
            Set<String> fondsIdList = new HashSet<>(16);
//            List<TBaseArchivesDb> tBaseArchivesDbList = tBaseArchivesDbService.findListByCondition(condition);
//            if (CollectionUtils.isNotEmpty(tBaseArchivesDbList)) {
//                tBaseArchivesDbList.forEach(tBaseArchivesDb -> fondsIdList.add(tBaseArchivesDb.getFondsId()));
//            }
//            if (CollectionUtils.isNotEmpty(fondsIdList)) {
//                fondsIdList.forEach(fondsId -> {
//                    List<TBaseArchTable> tBaseArchTables = tBaseArchTableMapper.findTableNameByFondsIdAndTableIden(fondsId);
//                    for (TBaseArchTable tBaseArchTable : tBaseArchTables) {
//                        String tableId = tBaseArchTable.getId();
//                        String tableName = tBaseArchTable.getTableName();
//                        try {
//                            //处理只有创建时间的，只有创建时间的，说明是原始型没有被修改
//                            List<String> documents4CreateTime = tBaseArchTableMapper.findIdByTableNameAndCreateTime(tableName);
//                            if (CollectionUtils.isNotEmpty(documents4CreateTime)) {
//                                xml4CreateOrEditTime(tableId, documents4CreateTime, "create");
//                            }
//                            //处理有修改时间的，有修改时间的说明是修改型或者生成多次
//                            List<String> documents4EditTime = tBaseArchTableMapper.findIdByTableNameAndEditTime(tableName);
//                            if (CollectionUtils.isNotEmpty(documents4EditTime)) {
//                                xml4CreateOrEditTime(tableId, documents4EditTime, "edit");
//                            }
//                            logger.info(tableName + " 表下所有数据执行完成 ！");
//                        } catch (Exception e) {
//                            logger.error("Table " + tableName + " doesn't exist ！ " + e.getMessage());
//                        }
//                    }
//                });
//            }
            logger.info(String.format("执行完成！%d", new Date().getDay()));
        }
    }

    /***
     * XML封装生成并检查是否成功
     *
     * @param tableId
     * @param archId
     */
    private void updateXmlAndIsSuccess(String tableId, String archId) {
//        xmlService.fileVol2XmlNotAsync(archId, tableId);
//        TBasePackagefile obj = packageFileMapper.findAll2ObjByArchId(archId);
//        boolean xmlIsExistAfter = checkXmlIsExist(obj.getFilePath(), String.valueOf(obj.getPathStatus()));
//        if (!xmlIsExistAfter) {
//            logger.error("生成封装EEP失败 archiveId:" + archId + "-date:" + DateUtils.getDateTime());
//        }
    }

    /***
     * 只有创建时间的 只有创建时间的 说明是原始型没有被修改
     * 如果有修改时间的 有修改时间的说明是修改型或者生成多次
     *
     * @param tableId
     * @param documentsAndVols
     * @author: osc_lihonglin
     * @date: 2021/11/25 15:20
     */
    private void xml4CreateOrEditTime(String tableId, List<String> documentsAndVols, String createOrEdit) {
        //线程控制器（计数器，当所有线程都执行完后再执行的控制器，同步多个任务的执行）
        CountDownLatch countDownLatch = new CountDownLatch(documentsAndVols.size());
        documentsAndVols.forEach(archId -> {
//            int exist = packageFileMapper.checkExistByArchId(archId);
            int exist = 0;
            switch (exist) {
                case 0:
                    //还未生成EEP的数据
                    if (StringUtils.isNotBlank(tableId)) {
                        taskExecutor.taskExecutor().execute(() -> {
                            updateXmlAndIsSuccess(tableId, archId);
                        });
                    }
                    countDownLatch.countDown();
                    break;
                case 1:
                    //如果只有创建时间只需要检测文件是否存在即可;判断不存在则新生成
                    if ("create".equals(createOrEdit)) {
//                        TBasePackagefile packagefile = packageFileMapper.findAll2ObjByArchId(archId);
                        //未被删除的数据 status：0 未删除（正常）;1 已删除;
                        if (0 == 0) {
                            boolean checkBefore = checkXmlIsExist("", "");
                            if (StringUtils.isNotBlank(tableId) && !checkBefore) {
                                taskExecutor.taskExecutor().execute(() -> {
                                    updateXmlAndIsSuccess(tableId, archId);
                                });
                            }
                        }
                    } else if ("edit".equals(createOrEdit)) {
                        //处理有修改时间的 有修改时间的说明是修改型或者生成多次;直接全部生成
                        if (StringUtils.isNotBlank(tableId)) {
                            taskExecutor.taskExecutor().execute(() -> {
                                updateXmlAndIsSuccess(tableId, archId);
                            });
                        }
                    }
                    countDownLatch.countDown();
                    break;
                default:
                    logger.error("请检查EEP数量，一份条目数据仅对应一份EEP archiveId:" + archId);
                    countDownLatch.countDown();
                    break;
            }
        });
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            //中断异常抓取
            e.printStackTrace();
        }
    }

    /**
     * 判断文件是否存在
     *
     * @param filePath
     * @param status
     * @return
     */
    private boolean checkXmlIsExist(String filePath, String status) {
//        String downLoadPath = fileConfig.getFileSaveRootPath("", status);
//        File file = new File(downLoadPath + filePath);
//        if (!file.exists()) {
//            return false;
//        }
        return true;
    }

    /**
     * 正式环境 schedule.electronic.cron 配置任务执行时间
     * <p>
     * 待解决问题：复制完成后，不能删除源文件（后续排查）
     * <p>
     * 需添加功能：多次处理失败记录过滤功能（后续添加）
     *
     * @author: osc_lihonglin
     * @date: 2021/10/12 10:04
     */
//    @Transactional(rollbackFor = Exception.class)
//    @Scheduled(cron = "${schedule.electronic.cron}")
//    public void cronJob() {
//        if (cronStatus.equals("open")) {
//            logger.debug("执行开始！" + DateUtils.getDateTime());
//            Map<String, Object> condition = new HashMap<>();
//            condition.put("notTemplate", "fonds_common_temp");
//            List<TBaseArchivesDb> tBaseArchivesDbList = tBaseArchivesDbService.findListByCondition(condition);
//            for (TBaseArchivesDb tBaseArchivesDb : tBaseArchivesDbList) {
//                //获取档案库电子文件挂载路径配置信息 //路径规则字段【英文】
//                String[] directSaveRule = xmlService.getElfRoute(tBaseArchivesDb.getId());
//                //获取档案库电子文件挂载名称配置信息 //文件名字段【英文】
//                String[] fileSaveRule = xmlService.getElfName(tBaseArchivesDb.getId());
//                if (directSaveRule != null && fileSaveRule != null) {
//                    //处理档案电子文件
//                    arrangeArchiveFile(directSaveRule, fileSaveRule, tBaseArchivesDb);
//                    //处理封装包文件--案卷级
//                    if (tBaseArchivesDb.getArchivesInFiles().equals("1")) {
//                        arrangePackageFile(directSaveRule, fileSaveRule, tBaseArchivesDb, TableIdenType.VOLUME);
//                    }
//                    //处理封装包文件--文件级
//                    arrangePackageFile(directSaveRule, fileSaveRule, tBaseArchivesDb, TableIdenType.DOCUMENT);
//                } else {
//                    logger.error("存储规则未设置：" + tBaseArchivesDb.getArchivesName());
//                }
//            }
//            logger.debug("执行完成！" + DateUtils.getDateTime());
//        }
//    }
//
//    /**
//     * 整理档案电子文件存储
//     *
//     * @param directSaveRule
//     * @param fileSaveRule
//     * @param tbaseArchivesDb
//     */
//    private void arrangeArchiveFile(String[] directSaveRule, String[] fileSaveRule, TBaseArchivesDb tbaseArchivesDb) {
//        //取档案库文件表信息
//        TBaseArchTable docArchTable = tBaseArchTableMapper.findOneByArchivesIdAndIden(tbaseArchivesDb.getId(), TableIdenType.DOCUMENT.getIndex());
//        Map<String, Object> condition = new HashMap<>();
//        condition.put("archivesId", tbaseArchivesDb.getId());
//        condition.put("tableName", docArchTable.getTableName());
//        condition.put("pathStatus", "0");
//        condition.put("status", "2");
//        //取待处理记录总数
//        int elecCount = dynamicTableMapper.getElectProcessArchCountByCondition(condition);
//        if (elecCount > 0) {
//            //根据每批次数量计算需处理次数，避免处理失败数据多次循环无法结束
//            int processCount = elecCount > processSize ? elecCount / processSize + 1 : 1;
//            //分批次处理数据，避免大数据查询处理超时
//            condition.put("pageStart", 0);
//            condition.put("pageSize", processSize);
//            do {
//                //取需处理的档案数据，避免存储规则转换时频繁查询档案数据表
//                List<Map<String, Object>> archiveDataList = dynamicTableMapper.findElectProcessArchDataByCondition(condition);
//                for (Map<String, Object> archData : archiveDataList) {
//                    //筛选档案关联电子文件条件
//                    Map<String, Object> elecCondition = new HashMap<>();
//                    elecCondition.put("archivesId", tbaseArchivesDb.getId());
//                    elecCondition.put("tableName", docArchTable.getTableName());
//                    elecCondition.put("pathStatus", "0");
//                    elecCondition.put("archiveId", archData.get("id"));
//                    List<TBaseElectronicRecord> electronicRecordList = tBaseElectronicRecordMapper.findListByCondition(elecCondition);
//                    for (TBaseElectronicRecord tbaseElectronicRecord : electronicRecordList) {
//                        //路径，扩展名
//                        String orgFilepath = tbaseElectronicRecord.getFilepath();
//                        String extension = tbaseElectronicRecord.getExtension();
//                        //源文件
//                        File sourceFile = new File(fileConfig.getCollectSavePath() + orgFilepath);
//                        if (sourceFile.exists()) {
//                            //获取文件目录dir
//                            String ruleRouteValue = xmlService.getRuleRoute(directSaveRule, archData);
//                            //获取文件名fineName
//                            String ruleNameValue = xmlService.getRuleName(fileSaveRule, archData);
//                            //复制文件到新目录
//                            String fileName = moveFile(sourceFile, ruleRouteValue, ruleNameValue + "." + extension);
//                            if (StringUtil.isNotEmpty(fileName)) {
//                                //更新电子文件存储路径，移动状态
//                                tbaseElectronicRecord.setPathStatus("1");
//                                tbaseElectronicRecord.setFilepath(FilenameUtils.separatorsToUnix(ruleRouteValue + fileName));
//                                tbaseElectronicRecord.setSavefilename(fileName);
//                                tBaseElectronicRecordMapper.updateById(tbaseElectronicRecord);
//                            }
//                        } else {
//                            logger.error("文件不存在：" + sourceFile.getAbsolutePath());
//                        }
//                    }
//                }
//            } while ((processCount -= 1) > 0);
//        }
//    }
//
//    /**
//     * 整理档案封装包存储
//     *
//     * @param directSaveRule
//     * @param fileSaveRule
//     * @param tbaseArchivesDb
//     */
//    private void arrangePackageFile(String[] directSaveRule, String[] fileSaveRule, TBaseArchivesDb tbaseArchivesDb, TableIdenType tableIden) {
//        //取档案库文件表信息
//        TBaseArchTable archTable = tBaseArchTableMapper.findOneByArchivesIdAndIden(tbaseArchivesDb.getId(), tableIden.getIndex());
//        Map<String, Object> condition = new HashMap<>();
//        condition.put("archivesId", tbaseArchivesDb.getId());
//        condition.put("tableName", archTable.getTableName());
//        condition.put("pathStatus", "0");
//        condition.put("status", "2");
//        //取待处理记录总数
//        int packageCount = dynamicTableMapper.getPackageProcessArchCountByCondition(condition);
//        if (packageCount > 0) {
//            //根据每批次数量计算需处理次数，避免处理失败数据多次循环无法结束
//            int processCount = packageCount > processSize ? packageCount / processSize + 1 : 1;
//            //分批次处理数据，避免大数据查询处理超时
//            condition.put("pageStart", 0);
//            condition.put("pageSize", processSize);
//            do {
//                List<Map<String, Object>> archiveDataList = dynamicTableMapper.findPackageProcessArchDataByCondition(condition);
//                for (Map<String, Object> archData : archiveDataList) {
//                    //筛选档案关联电子文件条件
//                    Map<String, Object> elecCondition = new HashMap<>();
//                    elecCondition.put("archivesId", tbaseArchivesDb.getId());
//                    elecCondition.put("tableName", archTable.getTableName());
//                    elecCondition.put("pathStatus", "0");
//                    elecCondition.put("archiveId", archData.get("id"));
//                    List<TBasePackagefile> tbasePackagefileListList = packageFileMapper.findListByCondition(elecCondition);
//                    for (TBasePackagefile tbasePackagefile : tbasePackagefileListList) {
//                        //路径，扩展名
//                        String orgFilepath = tbasePackagefile.getFilePath();
//                        String extension = "eep";
//                        //源文件
//                        File sourceFile = new File(fileConfig.getCollectSavePath() + orgFilepath);
//                        if (sourceFile.exists()) {
//                            String ruleRouteValue = "";
//                            String ruleNameValue = "";
//                            //取存储规则
//                            if (tableIden == TableIdenType.VOLUME) {
//                                ruleRouteValue = xmlService.getVolDirPath(tbaseArchivesDb.getId(), archData);
//                                ruleNameValue = archData.get("arch_code").toString();
//                            } else {
//                                ruleRouteValue = xmlService.getRuleRoute(directSaveRule, archData);
//                                ruleNameValue = xmlService.getRuleName(fileSaveRule, archData);
//                            }
//                            //复制文件到新目录
//                            String fileName = moveFile(sourceFile, ruleRouteValue, ruleNameValue + "." + extension);
//                            if (StringUtil.isNotEmpty(fileName)) {
//                                //更新eep存储位置，移动状态
//                                tbasePackagefile.setPathStatus(1);
//                                tbasePackagefile.setFilePath(FilenameUtils.separatorsToUnix(ruleRouteValue + fileName));
//                                tbasePackagefile.setSaveFileName(fileName);
//                                packageFileMapper.updateXmlFile(tbasePackagefile);
//                            }
//                        } else {
//                            logger.error("文件不存在：" + sourceFile.getAbsolutePath());
//                        }
//                    }
//                }
//            } while ((processCount -= 1) > 0);
//        }
//    }
//
//    /**
//     * 复制文件完成后，校验一致性
//     *
//     * @param sourceFile
//     * @param targetFile
//     * @return
//     */
//    private boolean verifyFileHash(File sourceFile, File targetFile) {
//        boolean result = false;
//        try {
//            if (sourceFile.exists() && targetFile.exists()) {
//                String sourceFileMD5 = DigestUtils.md5Hex(new FileInputStream(sourceFile));
//                String targetFileMD5 = DigestUtils.md5Hex(new FileInputStream(targetFile));
//                if (sourceFileMD5.equals(targetFileMD5)) {
//                    result = true;
//                }
//            }
//        } catch (IOException e) {
//            e.printStackTrace();
//        } finally {
//            return result;
//        }
//    }
//
//    /**
//     * 指定路径下按存储设置文件名进行检查，避免重名覆盖，并按流水顺序进行命名
//     *
//     * @param filePath
//     * @param fileName
//     * @return
//     */
//    private String getSaveFileName(String filePath, String fileName) {
//        String resultFile = fileConfig.getFileNameWithoutExtension(fileName);
//        String extension = fileConfig.getFileExtension(fileName);
//        int stepNum = 0;
//        File directory = new File(filePath);
//        for (int i = 0; i < directory.listFiles().length; i++) {
//            File file = directory.listFiles()[i];
//            if (file.isFile()) {
//                String tempFileName = fileConfig.getFileNameWithoutExtension(file.getName());
//                if (tempFileName.equals(resultFile)) {
//                    stepNum += 1;
//                    resultFile = fileConfig.getFileNameWithoutExtension(fileName) + "_" + String.valueOf(stepNum);
//                    //重置循环，避免漏检
//                    i = 0;
//                }
//            }
//        }
//        return resultFile + "." + extension;
//    }

    /**
     * 移动文件的公用过程
     *
     * @param sourceFile
     * @param targetPath
     * @param targetFileName
     * @return
     */
//    private String moveFile(File sourceFile, String targetPath, String targetFileName) {
//        String resultFileName = "";
//        try {
//            //目录不存在自动创建
//            File folder = new File(targetPath);
//            if (!folder.exists() && !folder.isDirectory()) {
//                folder.mkdirs();
//            }
//            File targetFile = null;
//            do {
//                //封装文件不做重名检测，规避名称出现序号问题
//                String tempFileName = targetFileName.endsWith(".eep") ? targetFileName : getSaveFileName(targetPath, targetFileName);
//                targetFile = new File( targetPath + tempFileName);
//                //复制前检查文件是否存在，目标文件已存在，重新检查获取新文件名，避免多并发问题
//                if (!targetFile.exists()) {
//                    //复制文件到新目录
//                    FileTool.copyFile(sourceFile, targetFile);
//                    //文件校验
//                    if (verifyFileHash(sourceFile, targetFile)) {
//                        logger.debug("移动文件到新目录成功");
//                        try {
//                            if (!targetFileName.endsWith(".eep")) {
//                                //同步复制ocr生成的txt文件
//                                File ocrSourceFile = new File(sourceFile.getAbsolutePath() + ".txt");
//                                if (ocrSourceFile.exists()) {
//                                    File ocrTargetFile = new File(targetFile.getAbsolutePath() + ".txt");
//                                    FileTool.copyFile(ocrSourceFile, ocrTargetFile);
//                                    if (verifyFileHash(ocrSourceFile, ocrTargetFile)) {
//                                        if (!FileTool.deleteQuietly(ocrSourceFile)) {
//                                            try {
//                                                FileTool.forceDelete(ocrSourceFile);
//                                            } catch (IOException ex) {
//                                                ex.printStackTrace();
//                                            }
//                                        }
//                                    }
//                                }
//                            }
//                            //删除源文件
//                            if (!FileTool.deleteQuietly(sourceFile)) {
//                                FileTool.forceDelete(sourceFile);
//                            }
//                        } catch (IOException ex) {
//                            ex.printStackTrace();
//                            logger.error(ex.toString());
//                        } finally {
//                            resultFileName = tempFileName;
//                        }
//                    } else {
//                        try {
//                            //失败删除复制的新文件
//                            if (targetFile.exists()) {
//                                if (!FileTool.deleteQuietly(targetFile)) {
//                                    FileTool.forceDelete(targetFile);
//                                }
//                            }
//                        } catch (IOException ex) {
//                            ex.printStackTrace();
//                            logger.error(ex.toString());
//                        } finally {
//                            logger.error("移动文件到新目录失败:" + sourceFile.getName());
//                        }
//                    }
//                } else {
//                    targetFile = null;
//                }
//            } while (targetFile == null);
//        } catch (IOException ex) {
//            ex.printStackTrace();
//            logger.error(ex.toString());
//        } finally {
//            return resultFileName;
//        }
//    }
}
